// SPDX-License-Identifier: GPL-2.0-only
/*
 * Core IIO driver for Bosch BMA400 triaxial acceleration sensor.
 *
 * Copyright 2019 Dan Robertson <dan@dlrobertson.com>
 *
 * TODO:
 *  - Support for power management
 *  - Support events and interrupts
 *  - Create channel for step count
 *  - Create channel for sensor time
 */
#include <linux/hwmon.h>
#include <linux/fs.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include "bma253.h"
#include <linux/kstrtox.h>
#include <linux/device.h>

#define BMA253_ACC_2G_MIN (-2 * 1024)
#define BMA253_ACC_2G_MAX (2 * 1024)

/*
 * The G-range selection may be one of 2g, 4g, 8, or 16g. The scale may
 * be selected with the acc_range bits of the ACC_CONFIG1 register.
 * NB: This buffer is populated in the device init.
 */
static int bma400_scales[8];

/*
 * See the ACC_CONFIG1 section of the datasheet.
 * NB: This buffer is populated in the device init.
 */
static int bma400_sample_freqs[14];

static const int bma400_osr_range[] = { 0, 1, 3 };

/* See the ACC_CONFIG0 section of the datasheet */
enum bma400_power_mode {
	POWER_MODE_SLEEP   = 0x00,
	POWER_MODE_LOW     = 0x01,
	POWER_MODE_NORMAL  = 0x02,
	POWER_MODE_INVALID = 0x03,
};

struct bma400_sample_freq {
	int hz;
	int uhz;
};

struct bma400_data {
	struct device *dev;
	struct regmap *regmap;
	struct regulator_bulk_data regulators[BMA400_NUM_REGULATORS];
	struct mutex mutex; /* data register lock */
	struct iio_mount_matrix orientation;
	enum bma400_power_mode power_mode;
	struct bma400_sample_freq sample_freq;
	int oversampling_ratio;
	int scale;
};



const struct regmap_config bma400_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.max_register = 0x3f,
};
EXPORT_SYMBOL(bma400_regmap_config);

static const struct iio_mount_matrix *
bma400_accel_get_mount_matrix(const struct iio_dev *indio_dev,
			      const struct iio_chan_spec *chan)
{
	struct bma400_data *data = iio_priv(indio_dev);

	return &data->orientation;
}

static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma400_accel_get_mount_matrix),
	{ }
};

#define BMA400_ACC_CHANNEL(_axis) { \
	.type = IIO_ACCEL, \
	.modified = 1, \
	.channel2 = IIO_MOD_##_axis, \
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
		BIT(IIO_CHAN_INFO_SCALE), \
}

static const struct iio_chan_spec bma400_channels[] = {
	BMA400_ACC_CHANNEL(X),
	BMA400_ACC_CHANNEL(Y),
	BMA400_ACC_CHANNEL(Z),
	{
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
	},
};

static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
{
	unsigned int raw_temp;
	int host_temp;
	int ret;

//	if (data->power_mode == POWER_MODE_SLEEP)
//		return -EBUSY;

	ret = regmap_read(data->regmap, 0x08, &raw_temp);
	if (ret)
		return ret;

	host_temp = sign_extend32(raw_temp, 7);
	/*
	 * The formula for the TEMP_DATA register in the datasheet
	 * is: x * 0.5 + 23
	 */
	*val = (host_temp / 2) + 23;
	*val2 = (host_temp & 0x1) * 500000;
	return IIO_VAL_INT_PLUS_MICRO;
}


static int bma400_get_accel_reg(struct bma400_data *data,
				const struct iio_chan_spec *chan,
				int *val)
{
	u8 raw_low;
	u8 raw_higt;
	int lsb_reg;
	int ret;

	switch (chan->channel2) {
	case IIO_MOD_X:
		lsb_reg = 0x02;
		break;
	case IIO_MOD_Y:
		lsb_reg = 0x04;
		break;
	case IIO_MOD_Z:
		lsb_reg = 0x06;
		break;
	default:
		dev_err(data->dev, "invalid axis channel modifier\n");
		return -EINVAL;
	}

	/* bulk read two registers, with the base being the LSB register */
	ret = regmap_bulk_read(data->regmap, lsb_reg, &raw_low,
			       sizeof(raw_low));
	if (ret)
		return ret;
	printk("raw_low is %d\n", raw_low);

	ret = regmap_bulk_read(data->regmap, lsb_reg + 1, &raw_higt,
		sizeof(raw_higt));
	if (ret)
 		return ret;
	printk("raw_higt is %d\n", raw_higt);

	*val = (u32)((raw_low >> 4) & 0x0F) | (u32)((raw_higt & 0xFF) << 4);
	printk("read raw data is %d\n", *val);
	

//	*val = sign_extend32(le16_to_cpu(raw_accel), 11);
	return IIO_VAL_INT;
}

static void bma400_output_data_rate_from_raw(int raw, unsigned int *val,
					     unsigned int *val2)
{
	*val = BMA400_ACC_ODR_MAX_HZ >> (BMA400_ACC_ODR_MAX_RAW - raw);
	if (raw > BMA400_ACC_ODR_MIN_RAW)
		*val2 = 0;
	else
		*val2 = 500000;
}


static int bma400_set_accel_output_data_rate(struct bma400_data *data,
					     int hz, int uhz)
{
	unsigned int idx;
	unsigned int odr;
	unsigned int val;
	int ret;

	if (hz >= BMA400_ACC_ODR_MIN_WHOLE_HZ) {
		if (uhz || hz > BMA400_ACC_ODR_MAX_HZ)
			return -EINVAL;

		/* Note this works because MIN_WHOLE_HZ is odd */
		idx = __ffs(hz);

		if (hz >> idx != BMA400_ACC_ODR_MIN_WHOLE_HZ)
			return -EINVAL;

		idx += BMA400_ACC_ODR_MIN_RAW + 1;
	} else if (hz == BMA400_ACC_ODR_MIN_HZ && uhz == 500000) {
		idx = BMA400_ACC_ODR_MIN_RAW;
	} else {
		return -EINVAL;
	}

	ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val);
	if (ret)
		return ret;

	/* preserve the range and normal mode osr */
	odr = (~BMA400_ACC_ODR_MASK & val) | idx;

	ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG, odr);
	if (ret)
		return ret;

	bma400_output_data_rate_from_raw(idx, &data->sample_freq.hz,
					 &data->sample_freq.uhz);
	return 0;
}


static int bma400_accel_scale_to_raw(struct bma400_data *data,
				     unsigned int val)
{
	int raw;

	if (val == 0)
		return -EINVAL;

	/* Note this works because BMA400_SCALE_MIN is odd */
	raw = __ffs(val);

	if (val >> raw != BMA400_SCALE_MIN)
		return -EINVAL;

	return raw;
}

static int bma400_set_accel_scale(struct bma400_data *data, unsigned int val)
{
	unsigned int acc_config;
	int raw;
	int ret;

	ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &acc_config);
	if (ret)
		return ret;

	raw = bma400_accel_scale_to_raw(data, val);
	if (raw < 0)
		return raw;

	ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG,
			   (acc_config & ~BMA400_ACC_SCALE_MASK) |
			   (raw << BMA400_SCALE_SHIFT));
	if (ret)
		return ret;

	data->scale = val;
	return 0;
}

//static int bma400_get_power_mode(struct bma400_data *data)
//{
//	unsigned int val;
//	int ret;
//
//	ret = regmap_read(data->regmap, BMA400_STATUS_REG, &val);
//	if (ret) {
//		dev_err(data->dev, "Failed to read status register\n");
//		return ret;
//	}
//
//	data->power_mode = (val >> 1) & BMA400_TWO_BITS_MASK;
//	return 0;
//}


static int bma253_init(struct bma400_data *data)
{
	int ret;

//	ret = regmap_write(data->regmap, 0x14, 182);
//	if (ret)
//	{
//		printk("reset error\n");
//		return ret;
//	}
//	printk("reset succeed\n");

	ret = regmap_write(data->regmap, 0x11, 0x00);
	ret = regmap_write(data->regmap, 0x0f, 0x03);
	ret = regmap_write(data->regmap, 0x10, 0x0f);
	ret = regmap_write(data->regmap, 0x18, 0x09);
	ret = regmap_write(data->regmap, 0x1b, 0x08);
	ret = regmap_write(data->regmap, 0x20, 0x05);
	ret = regmap_write(data->regmap, 0x21, 0x8e);
	ret = regmap_write(data->regmap, 0x27, 0x08);
	ret = regmap_write(data->regmap, 0x28, 0x40);
	//设置补偿
	ret = regmap_write(data->regmap, 0x3a, 0x11);		//z
	ret = regmap_write(data->regmap, 0x39, -13);		 //y 
	ret = regmap_write(data->regmap, 0x38, -1);

	if(ret)
	{
		printk("init error\n");
		return ret;
	}
	printk("init surrel\n");
	return 0;
}
static int bma400_set_accel_oversampling_ratio(struct bma400_data *data,
					       int val)
{
	unsigned int acc_config;
	int ret;

	if (val & ~BMA400_TWO_BITS_MASK)
		return -EINVAL;

	/*
	 * The oversampling ratio is stored in a different register
	 * based on the power-mode.
	 */
	switch (data->power_mode) {
	case POWER_MODE_LOW:
		ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG,
				  &acc_config);
		if (ret)
			return ret;

		ret = regmap_write(data->regmap, BMA400_ACC_CONFIG0_REG,
				   (acc_config & ~BMA400_LP_OSR_MASK) |
				   (val << BMA400_LP_OSR_SHIFT));
		if (ret) {
			dev_err(data->dev, "Failed to write out OSR\n");
			return ret;
		}

		data->oversampling_ratio = val;
		return 0;
	case POWER_MODE_NORMAL:
		ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG,
				  &acc_config);
		if (ret)
			return ret;

		ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG,
				   (acc_config & ~BMA400_NP_OSR_MASK) |
				   (val << BMA400_NP_OSR_SHIFT));
		if (ret) {
			dev_err(data->dev, "Failed to write out OSR\n");
			return ret;
		}

		data->oversampling_ratio = val;
		return 0;
	default:
		return -EINVAL;
	}
	return ret;
}

/*
static int bma400_init(struct bma400_data *data)
{
	unsigned int val;
	int ret;

	ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
	if (ret) {
		dev_err(data->dev, "Failed to read chip id register\n");
		goto out;
	}

	if (val != BMA400_ID_REG_VAL) {
		dev_err(data->dev, "Chip ID mismatch\n");
		ret = -ENODEV;
		goto out;
	}

	//电源管理
	data->regulators[BMA400_VDD_REGULATOR].supply = "vdd";
	data->regulators[BMA400_VDDIO_REGULATOR].supply = "vddio";
	ret = devm_regulator_bulk_get(data->dev,
				      ARRAY_SIZE(data->regulators),
				      data->regulators);
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(data->dev,
				"Failed to get regulators: %d\n",
				ret);

		goto out;
	}
	ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
				    data->regulators);
	if (ret) {
		dev_err(data->dev, "Failed to enable regulators: %d\n",
			ret);
		goto out;
	}

	//获取芯片电源模式
	ret = bma400_get_power_mode(data);
	if (ret) {
		dev_err(data->dev, "Failed to get the initial power-mode\n");
		goto err_reg_disable;
	}

	//设置芯片电源模式
	if (data->power_mode != POWER_MODE_NORMAL) {
		ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
		if (ret) {
			dev_err(data->dev, "Failed to wake up the device\n");
			goto err_reg_disable;
		}
		usleep_range(1500, 2000);
	}


	bma400_init_tables();

	ret = bma400_get_accel_output_data_rate(data);
	if (ret)
		goto err_reg_disable;

	ret = bma400_get_accel_oversampling_ratio(data);
	if (ret)
		goto err_reg_disable;

	ret = bma400_get_accel_scale(data);
	if (ret)
		goto err_reg_disable;

	return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00);

err_reg_disable:
	regulator_bulk_disable(ARRAY_SIZE(data->regulators),
			       data->regulators);
out:
	return ret;
}

*/

static const int accel_scale_bma253[] = {980000, 950000, 910000, 810000};


/*
	struct iio_dev *indio_dev  需要读写的 IIO 设备
	struct iio_chan_spec const *chan 需要读取的通道
	int *val, int *val2	读取的数据 val 是整数部分，val2 是小数部分
	long mask 掩码
*/
static int bma400_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan, int *val,
			   int *val2, long mask)
{
	struct bma400_data *data = iio_priv(indio_dev);
	int ret;
	int  scale;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		mutex_lock(&data->mutex);
		printk("read temp val\n");
		ret = bma400_get_temp_reg(data, val, val2);
		mutex_unlock(&data->mutex);
		return ret;
	case IIO_CHAN_INFO_RAW:
		mutex_lock(&data->mutex);
		ret = bma400_get_accel_reg(data, chan, val);
		mutex_unlock(&data->mutex);
		return ret;
	case IIO_CHAN_INFO_SAMP_FREQ:
		switch (chan->type) {
		case IIO_ACCEL:
			printk("read samp freq\n");
			if (data->sample_freq.hz < 0)
				return -EINVAL;

			*val = data->sample_freq.hz;
			*val2 = data->sample_freq.uhz;
			return IIO_VAL_INT_PLUS_MICRO;
		case IIO_TEMP:
			/*
			 * Runs at a fixed sampling frequency. See Section 4.4
			 * of the datasheet.
			 */
			*val = 6;
			*val2 = 250000;
			return IIO_VAL_INT_PLUS_MICRO;
		default:
			return -EINVAL;
		}
	case IIO_CHAN_INFO_SCALE:
		ret = regmap_read(data->regmap, 0x0f, &scale);
		if (ret)
			return ret;

		if(scale == 3)
		{
			*val = 0;
			*val2 = accel_scale_bma253[0];
		}
		else if(scale == 5)
		{
			*val = 1;
			*val2 = accel_scale_bma253[1];
		}
		else if(scale == 8)
		{
			*val = 3;
			*val2 = accel_scale_bma253[2];
		}
		else if(scale == 12)
		{
			*val = 7;
			*val2 = accel_scale_bma253[3];
		}
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
		/*
		 * TODO: We could avoid this logic and returning -EINVAL here if
		 * we set both the low-power and normal mode OSR registers when
		 * we configure the device.
		 */
		if (data->oversampling_ratio < 0)
			return -EINVAL;

		*val = data->oversampling_ratio;
		return IIO_VAL_INT;
	default:
		return -EINVAL;
	}
}

static int bma400_read_avail(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     const int **vals, int *type, int *length,
			     long mask)
{
	switch (mask) {
	case IIO_CHAN_INFO_SCALE:
		*type = IIO_VAL_INT_PLUS_MICRO;
		*vals = bma400_scales;
		*length = ARRAY_SIZE(bma400_scales);
		return IIO_AVAIL_LIST;
	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
		*type = IIO_VAL_INT;
		*vals = bma400_osr_range;
		*length = ARRAY_SIZE(bma400_osr_range);
		return IIO_AVAIL_RANGE;
	case IIO_CHAN_INFO_SAMP_FREQ:
		*type = IIO_VAL_INT_PLUS_MICRO;
		*vals = bma400_sample_freqs;
		*length = ARRAY_SIZE(bma400_sample_freqs);
		return IIO_AVAIL_LIST;
	default:
		return -EINVAL;
	}
}

static int bma400_write_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan, int val, int val2,
			    long mask)
{
	struct bma400_data *data = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_SAMP_FREQ:
		/*
		 * The sample frequency is readonly for the temperature
		 * register and a fixed value in low-power mode.
		 */
		if (chan->type != IIO_ACCEL)
			return -EINVAL;
		//设置加速度采样率
		mutex_lock(&data->mutex);
		ret = bma400_set_accel_output_data_rate(data, val, val2);
		mutex_unlock(&data->mutex);
		return ret;
	case IIO_CHAN_INFO_SCALE:
		if (val != 0 ||
		    val2 < BMA400_SCALE_MIN || val2 > BMA400_SCALE_MAX)
			return -EINVAL;
		printk("set scale\n");
		mutex_lock(&data->mutex);
		ret = bma400_set_accel_scale(data, val2);
		mutex_unlock(&data->mutex);
		return ret;
	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
		mutex_lock(&data->mutex);
		ret = bma400_set_accel_oversampling_ratio(data, val);
		mutex_unlock(&data->mutex);
		return ret;
	default:
		return -EINVAL;
	}
}

static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
				    struct iio_chan_spec const *chan,
				    long mask)
{
	switch (mask) {
	case IIO_CHAN_INFO_SAMP_FREQ:
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_SCALE:
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
		return IIO_VAL_INT;
	default:
		return -EINVAL;
	}
}

static const struct iio_info bma400_info = {
	.read_raw          = bma400_read_raw,       //内部读函数
	.read_avail        = bma400_read_avail,
	.write_raw         = bma400_write_raw,		//内部写函数
	.write_raw_get_fmt = bma400_write_raw_get_fmt, //用户空间向内核空间写入的数据格式
};

struct bma253_data{
	struct input_dev *input_dev;
	int irq_gpio_number;
	struct regmap *regmap;
	struct delayed_work ap_work; //等待队列实现定时采集数据
	int delay;      //delay的时间，ms为单位
	int enable;     //传感器工作状态
};


static ssize_t bma253_delay_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct bma253_data *data;
    int count;
    printk("enter\n");
/*
    client = to_i2c_client(dev);
	if(IS_ERR(client)) {
		printk("client is error fp\n");
		return 0;
	}
	
    data = i2c_get_clientdata(client);
	if(IS_ERR(data)) {
		printk("data is error fp\n");
		return 0;
	}
*/

	data = dev_get_drvdata(dev);

	printk("data delay %d, data input name %s\n",data->delay, data->input_dev->name);	
    snprintf(buf, 8, "%d\n", data->delay);
    count = strlen(buf);
    return count;
}


static ssize_t bma253_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    struct bma253_data *data;
    int tmp_delay;
	int ret;
    printk("buf: %s\n", buf);


	data = dev_get_drvdata(dev);

    ret = kstrtoint(buf, 10, &tmp_delay);   //字符串转换为整数
    printk("tmp_delay %d\n", tmp_delay);
    if (tmp_delay >= 0 && tmp_delay < 100000000) {
        data->delay = tmp_delay;
    } else {
        printk("ERROR: the delay value %d is unvalid\n", tmp_delay);
    }

    return count;
}


static ssize_t bma253_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct bma253_data *data;
    int count;
    printk("enter\n");

	data = dev_get_drvdata(dev);

	printk("data->enable is %d\n",data->enable);

    snprintf(buf, 8, "%d\n", data->enable);
    count = strlen(buf);
    return count;
}


ssize_t bma253_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    struct bma253_data *data;
    int tmp_enable;
    unsigned long delay;
	int ret;
	printk("buf: %s\n", buf);

    data = dev_get_drvdata(dev);

    ret = kstrtoint(buf, 10, &tmp_enable);
    printk("tmp_enable %d\n", tmp_enable);
    if (tmp_enable == 0 && data->enable == 1) {
        data->enable = 0;
		ret = cancel_delayed_work_sync(&data->ap_work);
		if (!ret) {
       		printk("ERROR: cancel schedule delay work failed\n");
    	}
		ret = regmap_write(data->regmap, 0x12, 0x40);
		ret = regmap_write(data->regmap, 0x11, 0x80);
		if(ret)
		{
			printk("init error\n");
		}

    } else if(tmp_enable == 1 && data->enable == 0){
        	data->enable = 1;
			ret = regmap_write(data->regmap, 0x14, 0xb6);
			mdelay(20);
			ret = regmap_write(data->regmap, 0x11, 0x00);
			ret = regmap_write(data->regmap, 0x0f, 0x03);
			ret = regmap_write(data->regmap, 0x10, 0x0f);
			ret = regmap_write(data->regmap, 0x18, 0x09);
			ret = regmap_write(data->regmap, 0x1b, 0x08);
			ret = regmap_write(data->regmap, 0x20, 0x05);
			ret = regmap_write(data->regmap, 0x21, 0x8e);
			ret = regmap_write(data->regmap, 0x27, 0x08);
			ret = regmap_write(data->regmap, 0x28, 0x40);
			//设置补偿
			ret = regmap_write(data->regmap, 0x3a, 0x11);       //z
			ret = regmap_write(data->regmap, 0x39, -13);         //y 
			ret = regmap_write(data->regmap, 0x38, -1);
			
			if(ret)
			{
				printk("init error\n");
			}

			delay = msecs_to_jiffies(data->delay); //延时时间
		

    		ret = schedule_delayed_work(&data->ap_work, delay); /* 返回值是bool */
    		if (!ret) {
	        	printk("ERROR: schedule delay work failed\n");
    		}
		
    }else {
			printk("repetitive operation\n");
	}

    return count;
}

static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR | S_IWGRP,
                   bma253_delay_show, bma253_delay_store);

static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
                   bma253_enable_show, bma253_enable_store);

static struct attribute *bma253_attributes[] = {
    &dev_attr_delay.attr,
    &dev_attr_enable.attr,
    NULL
};

static struct attribute_group bma253_attribute_group = {
    .attrs = bma253_attributes
};


int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
{
	struct iio_dev *indio_dev;
	struct bma400_data *data;
	int ret;

	//申请iio_dev，并设置私有数据
	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
	if (!indio_dev)
		return -ENOMEM;

	//获取私有数据的首地址
	data = iio_priv(indio_dev);
	data->regmap = regmap;
	data->dev = dev;

	//初始化芯片
//	ret = bma400_init(data);
	ret = bma253_init(data);
	if (ret)
		return ret;


	mutex_init(&data->mutex);
	indio_dev->name = name;  //名字
	indio_dev->info = &bma400_info; //实际调用的函数
	indio_dev->channels = bma400_channels; //通道，内核用iio_chan_spec来描述一个通道
	indio_dev->num_channels = ARRAY_SIZE(bma400_channels); //通道数
	indio_dev->modes = INDIO_DIRECT_MODE;

	//设置device的私有数据
	dev_set_drvdata(dev, indio_dev);

	//注册iio_dev
	return iio_device_register(indio_dev);
}
EXPORT_SYMBOL(bma400_probe);

int bma400_remove(struct device *dev, struct i2c_client* client)
{
	struct iio_dev *indio_dev = dev_get_drvdata(dev);
	if(indio_dev)
		iio_device_unregister(indio_dev);
	

	printk("55555555555555555\n");
	return 0;
}
EXPORT_SYMBOL(bma400_remove);


static irqreturn_t bma253_irq_handler(int irq, void *dev_id)
{
	struct bma253_data* data = (struct bma253_data*)(dev_id);
	int x, y, z;
	int ret;
	u8 raw_x_low, raw_x_higt;
	u8 raw_y_low, raw_y_higt;
	u8 raw_z_low, raw_z_higt;

	ret = regmap_bulk_read(data->regmap, 0x02, &raw_x_low,
                               sizeof(raw_x_low));
        if (ret)
                return ret;
//	printk("raw_x_low is %d\n", raw_x_low);
        ret = regmap_bulk_read(data->regmap, 0x03, &raw_x_higt,
                sizeof(raw_x_higt));
        if (ret)
                return ret;
//        printk("raw_x_higt is %d\n", raw_x_higt);
        x = (u32)((raw_x_low >> 4) & 0x0F) | (((u32)(raw_x_higt & 0xFF)) << 4);
//        printk("read rawx data is %d\n", x);


	ret = regmap_bulk_read(data->regmap, 0x04, &raw_y_low,
                               sizeof(raw_y_low));
        if (ret)
                return ret;
//        printk("raw_y_low is %d\n", raw_y_low);
        ret = regmap_bulk_read(data->regmap, 0x05, &raw_y_higt,
                sizeof(raw_y_higt));
        if (ret)
                return ret;
//        printk("raw_y_higt is %d\n", raw_y_higt);
        y = (u32)((raw_y_low >> 4) & 0x0F) | (((u32)(raw_y_higt & 0xFF)) << 4);
//        printk("read rawy data is %d\n", y);


	ret = regmap_bulk_read(data->regmap, 0x06, &raw_z_low,
                               sizeof(raw_z_low));
        if (ret)
                return ret;
//        printk("raw_z_low is %d\n", raw_z_low);
        ret = regmap_bulk_read(data->regmap, 0x07, &raw_z_higt,
                sizeof(raw_z_higt));
        if (ret)
                return ret;
//        printk("raw_z_higt is %d\n", raw_z_higt);
        z = (u32)((raw_z_low >> 4) & 0x0F) | (((u32)(raw_z_higt & 0xFF)) << 4);
//        printk("read rawz data is %d\n", x);


	//上报数据
	input_report_abs(data->input_dev, ABS_X, x);
	input_report_abs(data->input_dev, ABS_Y, y);
	input_report_abs(data->input_dev, ABS_Z, z);
        input_sync(data->input_dev);
	return IRQ_HANDLED;
}


static void bma253_read_fun(struct work_struct *work)
{
	struct bma253_data* data;
	int x, y, z;
	int ret;
	u8 raw_x_low, raw_x_higt;
	u8 raw_y_low, raw_y_higt;
	u8 raw_z_low, raw_z_higt;
	unsigned long delay;

	data = container_of((struct delayed_work *)work, struct bma253_data, ap_work);
	
//		printk("thread function runing\n");
		ret = regmap_bulk_read(data->regmap, 0x02, &raw_x_low,
                	               sizeof(raw_x_low));
        	if (ret)
                	return;
//        	printk("raw_x_low is %d\n", raw_x_low);
        	ret = regmap_bulk_read(data->regmap, 0x03, &raw_x_higt,
                			sizeof(raw_x_higt));
        	if (ret)
                	return;
//        	printk("raw_x_higt is %d\n", raw_x_higt);
        	x = (u32)((raw_x_low >> 4) & 0x0F) | (u32)(((u32)(raw_x_higt & 0xFF)) << 4);
			x = (x & 0x800) ? (x - 4096) : x;
//        	printk("read rawx data is %d\n", x);


		ret = regmap_bulk_read(data->regmap, 0x04, &raw_y_low,
               		                sizeof(raw_y_low));
        	if (ret)
                	return;
//        	printk("raw_y_low is %d\n", raw_y_low);
        	ret = regmap_bulk_read(data->regmap, 0x05, &raw_y_higt,
                sizeof(raw_y_higt));
        	if (ret)
                	return;
//        	printk("raw_y_higt is %d\n", raw_y_higt);
        	y = (u32)((raw_y_low >> 4) & 0x0F) | (((u32)(raw_y_higt & 0xFF)) << 4);
			y = (y & 0x800) ? (y - 4096) : y;
//        	printk("read rawy data is %d\n", y);


		ret = regmap_bulk_read(data->regmap, 0x06, &raw_z_low,
                               sizeof(raw_z_low));
        	if (ret)
                	return;
//        	printk("raw_z_low is %d\n", raw_z_low);
        	ret = regmap_bulk_read(data->regmap, 0x07, &raw_z_higt,
                		sizeof(raw_z_higt));
        	if (ret)
                	return;
//        	printk("raw_z_higt is %d\n", raw_z_higt);
        	z = (u32)((raw_z_low >> 4) & 0x0F) | (((u32)(raw_z_higt & 0xFF)) << 4);
			z = (z & 0x800) ? (z - 4096) : z;
//        	printk("read rawz data is %d\n", z);


		//上报数据
		input_report_abs(data->input_dev, ABS_X, x);
		input_report_abs(data->input_dev, ABS_Y, y);
		input_report_abs(data->input_dev, ABS_Z, z);
        input_sync(data->input_dev);
			
//	printk("bma253_read_fun exit\n");

	delay = msecs_to_jiffies(data->delay);


	ret = schedule_delayed_work(&data->ap_work, delay);
    if (!ret) {
        printk("ERROR: schedule delay work failed\n");
        return;
    }

	
	return;
}

static int bma400_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
{
    struct regmap *regmap;
	int ret;
	struct bma253_data *data;
	unsigned long delay;


	data = devm_kzalloc(&client->dev, sizeof(struct bma253_data), GFP_KERNEL);
    	if(!data)
   	{
        	dev_err(&client->dev, "device memory request failed\n");
		return -ENOMEM;
    	}


        regmap = devm_regmap_init_i2c(client, &bma400_regmap_config);
        if (IS_ERR(regmap)) {
                dev_err(&client->dev, "failed to create regmap\n");
                return PTR_ERR(regmap);
        }

	data->regmap = regmap;	
        //input子系统
        data->input_dev = devm_input_allocate_device(&client->dev);
        if (data->input_dev == NULL) {
                printk("input allocatre error\n");
                return -ENOMEM;
        }

        data->input_dev->name = "bma253";
        data->input_dev->id.bustype = BUS_I2C;
        input_set_capability(data->input_dev, EV_ABS, ABS_MISC);
        input_set_abs_params(data->input_dev, ABS_X, BMA253_ACC_2G_MIN, BMA253_ACC_2G_MAX, 0, 0);
        input_set_abs_params(data->input_dev, ABS_Y, BMA253_ACC_2G_MIN, BMA253_ACC_2G_MAX, 0, 0);
        input_set_abs_params(data->input_dev, ABS_Z, BMA253_ACC_2G_MIN, BMA253_ACC_2G_MAX, 0, 0);

        ret = input_register_device(data->input_dev);
        if (ret < 0) {
                printk("acc input can't register device!\n");
                input_free_device(data->input_dev);
                return ret;
        }
	printk("input register succeed\n");
		dev_set_drvdata(&data->input_dev->dev, data);

        //中断
        data->irq_gpio_number = of_get_named_gpio(client->dev.of_node, "ctp_int_port", 0);
	if (!gpio_is_valid(data->irq_gpio_number)) 
    	{
            	printk("Failed to get interrupt gpio\n");
            	return data->irq_gpio_number;
   	}
	printk("get interrupt gpio succeed\n");


	ret = devm_gpio_request(&client->dev, data->irq_gpio_number, "BTL INT IRQ");
	if (ret < 0)
	{
        	printk("Failed to request GPIO Int:%d, ERRNO:%d", (s32)data->irq_gpio_number, ret);
		return -ENODEV;
    	}
	printk("gpio request succeed\n");

	gpio_direction_input(data->irq_gpio_number);

        ret  = devm_request_irq(&client->dev, gpio_to_irq(data->irq_gpio_number),
                       bma253_irq_handler,
                       IRQF_TRIGGER_FALLING,
                       client->name,
                       data);

	if (ret)
    	{	
		printk("request irq error\n");
		return -1;
	}
	printk("request irq succeed\n");


	i2c_set_clientdata(client, data);

	data->enable = 1;
	data->delay = 66;
	printk("data enable and delay set ok\n");

	INIT_DELAYED_WORK(&data->ap_work, bma253_read_fun);
	delay = msecs_to_jiffies(data->delay);
	ret = schedule_delayed_work(&data->ap_work, delay);
	
	ret = sysfs_create_group(&data->input_dev->dev.kobj, &bma253_attribute_group);
    if (ret) {
        printk("ERROR: create sysfs group failed\n");
        cancel_delayed_work_sync(&data->ap_work);
		return ret;
    }


    return bma400_probe(&client->dev, regmap, id->name);
}

static int bma400_i2c_remove(struct i2c_client *client)
{
	printk("remove 1\n");
	return bma400_remove(&client->dev, client);
}

static const struct i2c_device_id bma400_i2c_ids[] = {
        { "bma400", 0 },
        { }
};
MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids);

static const struct of_device_id bma400_of_i2c_match[] = {
        { .compatible = "bosch,bma400" },
        { }
};
MODULE_DEVICE_TABLE(of, bma400_of_i2c_match);

static struct i2c_driver bma400_i2c_driver = {
        .driver = {
                .name = "bma400",
                .of_match_table = bma400_of_i2c_match,
        },
        .probe    = bma400_i2c_probe,
        .remove   = bma400_i2c_remove,
        .id_table = bma400_i2c_ids,
};

module_i2c_driver(bma400_i2c_driver);

MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (I2C)");
MODULE_LICENSE("GPL");

